package encrypt

import (
	"encoding/xml"
	"fmt"
	"github.com/beevik/etree"
	"io"
	"strings"
)

// 将结构体转换为xml
func StructToXml(structObj interface{}) ([]byte, error) {
	xml_data, err := xml.MarshalIndent(structObj, "", "  ")
	if err != nil {
		return nil, err
	}
	return xml_data, nil
}

// 将xml转换为结构体
func XmlToStruct(xml_data []byte, structObj interface{}) error {
	err := xml.Unmarshal(xml_data, structObj)
	if err != nil {
		return err
	}
	return nil
}

type MyDocument struct {
	document *etree.Document
	ele      *etree.Element
	a        *etree.Attr
}

// 创建XML对象
func NewDocument() *MyDocument {
	return &MyDocument{
		document: etree.NewDocument(),
	}
}

// 读取xml文件
func ReadXmlFile(filename string) *MyDocument {
	document := etree.NewDocument()
	if err := document.ReadFromFile(filename); err != nil {
		fmt.Println(err.Error())
		return nil
	}
	return &MyDocument{
		document: document,
	}
}

// 读取xml字符串
func ReadXmlString(xmlStr string) *MyDocument {
	document := etree.NewDocument()
	if err := document.ReadFromString(xmlStr); err != nil {
		fmt.Println(err.Error())
		return nil
	}
	return &MyDocument{
		document: document,
	}
}

// 读取io.Reader xml
func ReadXmlReader(reader io.Reader) *MyDocument {
	document := etree.NewDocument()
	n, err := document.ReadFrom(reader)
	if err != nil {
		fmt.Println(err.Error())
		return nil
	}
	if n == 0 {
		fmt.Println(err.Error())
		return nil
	}
	return &MyDocument{
		document: document,
	}
}

// 搜索指定节点,返回第一个匹配的节点的文本
func (d *MyDocument) SearchNode(path string, result *string) *MyDocument {
	element := d.document.FindElement(path)
	d.ele = element
	text := element.Text()
	if result != nil {
		*result = strings.TrimSpace(text)
	}
	return d
}

// 获取节点属性
func (d *MyDocument) GetNodeAttr(key string, result *string) *MyDocument {
	attr := d.ele.SelectAttr(key)
	d.a = attr
	text := attr.Value
	*result = text
	return d
}

// 创建节点,在当前节点下创建
func (d *MyDocument) CreateNode(tag, text string) *MyDocument {
	element := d.ele.CreateElement(tag)
	element.SetText(text)
	d.ele = element
	return d
}

// 创建节点属性
func (d *MyDocument) CreateNodeAttr(key, value string) *MyDocument {
	attr := d.ele.CreateAttr(key, value)
	d.a = attr
	return d
}

//==================================下面都是终结方法==================================

// 写入xml文件
func (d *MyDocument) WriteXmlFile(filename string) {
	if err := d.document.WriteToFile(filename); err != nil {
		fmt.Println(err.Error())
	}
}

// 将Document对象转换为字符串
func (d *MyDocument) WriteXmlString() (string, error) {
	return d.document.WriteToString()
}

// 将Document对象转换为字节
func (d *MyDocument) WriteXmlBytes() ([]byte, error) {
	return d.document.WriteToBytes()
}

// 搜索指定节点,返回所有匹配的节点的文本
func (d *MyDocument) SearchNodes(path string) []*etree.Element {
	path1 := etree.MustCompilePath(path)
	return d.document.FindElementsPath(path1)
}
